// Copyright Daniel Wallin 2007. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <cctype>
#include <iostream>

#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <libtorrent/torrent.hpp>
#include <libtorrent/extensions.hpp>
#include <libtorrent/entry.hpp>
#include <libtorrent/lazy_entry.hpp>
#include <libtorrent/aux_/session_impl.hpp>

using namespace boost::python;
using namespace libtorrent;

namespace
{
    struct plugin_wrap : plugin, wrapper<plugin>
    {
        boost::shared_ptr<torrent_plugin> new_torrent(torrent* t, void* user)
        {
            return plugin::new_torrent(t, user);
        }
        boost::shared_ptr<torrent_plugin> default_new_torrent(torrent* t, void* user)
        {
            return this->plugin::new_torrent(t, user);
        }

        void added(boost::weak_ptr<aux::session_impl> s)
        {
            if (override f = this->get_override("added")) {
                f(s);
            } else {
                plugin::added(s);
            }
        }
        void default_added(boost::weak_ptr<aux::session_impl> s)
        {
            this->plugin::added(s);
        }

        void on_alert(alert const* a)
        {
            if (override f = this->get_override("on_alert")) {
                f(std::auto_ptr<const alert>(a));
            } else {
                plugin::on_alert(a);
            }
        }
        void default_on_alert(alert const* a)
        {
            this->plugin::on_alert(a);
        }

        void on_tick()
        {
            if (override f = this->get_override("on_tick")) {
                f();
            } else {
                plugin::on_tick();
            }
        }
        void default_on_tick()
        {
            this->plugin::on_tick();
        }

        void save_state(entry& ent) const
        {
            if (override f = this->get_override("save_state")) {
                ent = call<entry>(f.ptr(), ent);
            } else {
                plugin::save_state(ent);
            }
        }
        void default_save_state(entry& ent) const
        {
            this->plugin::save_state(ent);
        }


        void load_state(lazy_entry const& ent)
        {
            if (override f = this->get_override("load_state")) {
                f(ent);
            } else {
                plugin::load_state(ent);
            }
        }
        void default_load_state(lazy_entry const& ent)
        {
            this->plugin::load_state(ent);
        }

        boost::weak_ptr<torrent> on_find_torrent(sha1_hash const& info_hash, boost::weak_ptr<torrent> t, bool use_extended_pool)
        {
            if (override f = this->get_override("on_find_torrent")) {
                return f(info_hash, t, use_extended_pool);
            } else {
                return plugin::on_find_torrent(info_hash, t, use_extended_pool);
            }
        }
        boost::weak_ptr<torrent> default_on_find_torrent(sha1_hash const& info_hash, boost::weak_ptr<torrent> t, bool use_extended_pool)
        {
            return this->plugin::on_find_torrent(info_hash, t, use_extended_pool);
        }

    };

} // namespace unnamed

void bind_plugin()
{
    class_<
        plugin_wrap, boost::shared_ptr<plugin_wrap>, boost::noncopyable
    >("plugin")
        .def(
            "new_torrent"
          , &plugin::new_torrent, &plugin_wrap::default_new_torrent
        )
        .def(
            "added"
          , &plugin::added, &plugin_wrap::default_added
        )
        .def(
            "on_alert"
          , &plugin::on_alert, &plugin_wrap::default_on_alert
        )
        .def(
            "on_tick"
          , &plugin::on_tick, &plugin_wrap::default_on_tick
        )
        .def(
            "save_state"
          , &plugin::save_state, &plugin_wrap::default_save_state
        )
        .def(
            "load_state"
          , &plugin::load_state, &plugin_wrap::default_load_state
        )
        .def(
            "on_find_torrent"
          , &plugin::on_find_torrent, &plugin_wrap::default_on_find_torrent
        )
        ;

    class_<std::map<std::string, std::string> >("string_map")
        .def(map_indexing_suite<std::map<std::string, std::string> >())
    ;

    class_<plugin, boost::shared_ptr<plugin> >("plugin", no_init);
}

